package com.bean.singleton;

/**
 * 单例模式
 * 指一个类只有一个实例，且该类能自行创建这个实例的一种模式。例如，Windows 中只能打开一个任务管理器，
 * 这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费，或出现各个窗口显示内容的不一致等错误。
 *
 * @author 顾志杰
 * @date 2021/8/2-10:07
 */
public class Singleton {

    /**
     * 单例模式有 3 个特点：
     * 1.单例类只有一个实例对象；
     * 2.该单例对象必须由单例类自行创建；
     * 3.单例类对外提供一个访问该单例的全局访问点。
     * <p>
     * 单例模式的优点和缺点
     * 单例模式的优点：
     * 单例模式可以保证内存里只有一个实例，减少了内存的开销。
     * 可以避免对资源的多重占用。
     * 单例模式设置全局访问点，可以优化和共享资源的访问。
     * <p>
     * 单例模式的缺点：
     * 单例模式一般没有接口，扩展困难。如果要扩展，则除了修改原来的代码，没有第二种途径，违背开闭原则。
     * 在并发测试中，单例模式不利于代码调试。在调试过程中，如果单例中的代码没有执行完，也不能模拟生成一个新的对象。
     * 单例模式的功能代码通常写在一个类中，如果功能设计不合理，则很容易违背单一职责原则。
     */

    public static void main(String[] args) {
        Lazy zt1 = Lazy.getInstance();
        zt1.getBean();    //输出实例
        Lazy zt2 = Lazy.getInstance();
        zt2.getBean();    //输出实例
        if (zt1 == zt2) {
            System.out.println("他们是同一实例！");
        } else {
            System.out.println("他们不是同一实例！");
        }
        System.out.println("------------------------------------无耻的分割线---------------------------------------");
        Hungry obj1 = Hungry.getInstance();
        Hungry obj2 = Hungry.getInstance();
        if (obj1 == obj2) {
            System.out.println("他们是同一实例！");
        } else {
            System.out.println("他们不是同一实例！");
        }

    }


}

/**
 * 懒汉模式
 */
class Lazy {
    private static volatile Lazy instance = null;    //保证instance在所有线程中同步

    //private避免类在外部被实例化
    private Lazy() {
        System.out.println("产生一个实例！");
    }

    public static synchronized Lazy getInstance() {
        //在getInstance方法上加同步
        if (instance == null) {
            instance = new Lazy();
        } else {
            System.out.println("已经有一个实例，不能产生新实例！");
        }
        return instance;
    }

    public void getBean() {
        System.out.println("我是新的实例。");
    }
}

/**
 * 饿汉模式
 */
class Hungry {
    private static Hungry instance = new Hungry();

    private Hungry() {

    }

    public static Hungry getInstance() {
        return instance;
    }
}
